﻿using System.Collections.Generic;

namespace RouteMaster
{
    public class AllRoutes
    {
        public readonly Dictionary<int, BusRoute> _routes = new Dictionary<int, BusRoute>();

        public void Add(BusRoute br)
        {
            _routes.Add(br.ID, br);
        }

        public bool IsPossibleRoute(BusStop from, BusStop to, RouteItinerary changes)
        {
            bool brc = IsPossibleRouteInner(from, to, changes);
            if (!brc)
                return false;

            changes.Reverse();
            changes.Add(new RouteLeg(null, to));
            changes.Reverse();
            return true;
        }

        private bool IsPossibleRouteInner(BusStop from, BusStop to, RouteItinerary changes)
        {
            return IsPossibleRouteInner1(from, to, changes, _routes);
        }

        private bool IsPossibleRouteInner1(BusStop from, BusStop to, RouteItinerary changes, Dictionary<int, BusRoute> routes1)
        {
            RouteMatcher m = new RouteMatcher();
            if (!m.RMIsPossibleRouteInner(from, to, changes, routes1))
                return false;

            int weightOriginal = changes.GetWeightTo(to);

            List<int> busRouteIDs = new List<int>();

            foreach (var ri in changes)
            {
                if (ri._busRoute != null)
                {
                    busRouteIDs.Add(ri._busRoute.ID);
                }
            }

            List<Attempt> attemptsx = new List<Attempt>();

            for (int x = 0; x < busRouteIDs.Count; x++)
            {
                Dictionary<int, BusRoute> testRoutes = new Dictionary<int, BusRoute>();

                foreach (BusRoute br in routes1.Values)
                {
                    if (br.ID == busRouteIDs[x])
                        continue;

                    testRoutes.Add(br.ID, br);
                }

                RouteItinerary changes1 = new RouteItinerary();

                if (m.RMIsPossibleRouteInner(from, to, changes1, testRoutes))
                {
                    int weight = changes1.GetWeightTo(to);
                    if (weight < weightOriginal)
                    {
                        Attempt attempt = new Attempt();
                        attempt._changesTemp = changes1;
                        attempt._weight = weight;
                        attemptsx.Add(attempt);
                    }
                }
            }

            int bestWeight = int.MaxValue;
            
            if (attemptsx.Count != 0)
            {
                Attempt candidate = null;
                foreach (Attempt a in attemptsx)
                {
                    if (a._weight < bestWeight)
                    {
                        candidate = a;
                        bestWeight = a._weight;
                    }
                }
                if (candidate != null)
                {
                    changes.Clear();
                    changes.AddRange(candidate._changesTemp);
                    return true;
                }
            }

            return true;
        }
    }
}
